// -----------------------------------------------------------------------
//  <copyright file="IdentityExtensions.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2024 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2024/12/10 20:06:07</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Mapping;


namespace DaprPlus.Identity.Application;

public static class IdentityExtensions
{
    /// <summary>
    /// 获取用户编号
    /// </summary>
    public static long GetUserId(this IIdentity identity)
    {
        if (identity is not ClaimsIdentity claimsIdentity)
        {
            return default;
        }

        var value = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        return long.TryParse(value, out var id) ? id : default;
    }

    /// <summary>
    /// 快速创建错误信息的IdentityResult
    /// </summary>
    public static IdentityResult Failed(this IdentityResult identityResult, params string[] errors)
    {
        var identityErrors = identityResult.Errors;
        identityErrors = identityErrors.Union(errors.Select(m => new IdentityError() { Description = m }));
        return IdentityResult.Failed(identityErrors.ToArray());
    }

    public static ApiResult ToApiResult(this IdentityResult identityResult)
    {
        return identityResult.Succeeded
            ? new ApiResult(ApiResultType.Success)
            : new ApiResult(ApiResultType.Error, identityResult.ErrorMessage());
    }

    public static ApiResult<TResult> ToApiResult<TResult>(this IdentityResult identityResult, TResult data)
    {
        return identityResult.Succeeded
            ? ApiResult<TResult>.Success(data)
            : new ApiResult<TResult>(ApiResultType.Error, identityResult.ErrorMessage());
    }
    public static string? ErrorMessage(this IdentityResult identityResult)
    {
        if (identityResult.Succeeded)
        {
            return null;
        }

        return identityResult.Errors.Select(m => m.Description).ExpandAndToString("; ");
    }

    /// <summary>
    /// 将登录结果SignResult转换为ApiResult
    /// </summary>
    public static ApiResult<TResult> ToApiResult<TUser, TResult>(this SignInResult signInResult, UserManager<TUser> userManager, TUser user)
        where TUser : UserBase
    {
        var data = user.MapTo<TResult>();
        if (signInResult.IsNotAllowed)
        {
            if (userManager.Options.SignIn.RequireConfirmedEmail && !user.EmailConfirmed)
            {
                return ApiResult<TResult>.Error(ResIdentity.String_Login_EmailNotConfirmed, data);
            }

            if (userManager.Options.SignIn.RequireConfirmedPhoneNumber && !user.PhoneNumberConfirmed)
            {
                return ApiResult<TResult>.Error(ResIdentity.String_Login_PhoneNumberNotConfirmed, data);
            }
            return ApiResult<TResult>.Error(ResIdentity.String_Login_NotAllowed, data);
        }

        if (signInResult.IsLockedOut)
        {
            return ApiResult<TResult>.Error(ResIdentity.Format_Login_LockupMinutes
                .FormatWith(userManager.Options.Lockout.DefaultLockoutTimeSpan.TotalMinutes));
        }

        if (signInResult.RequiresTwoFactor)
        {
            return ApiResult<TResult>.Error(ResIdentity.String_Login_TwoFactor, data);
        }

        if (signInResult.Succeeded)
        {
            return ApiResult<TResult>.Success(ResIdentity.String_Login_LoginSuccess, data);
        }

        return ApiResult<TResult>.Error(ResIdentity.Format_Login_LeftLoginAllowedTimes
            .FormatWith(userManager.Options.Lockout.MaxFailedAccessAttempts - user.AccessFailedCount), data);
    }
}
